package model

import (
	"context"
	"gorm.io/gorm"
	"sale_system/goods_srv/global"
	"strconv"
)

// 先定义表来作为商品表的外键

type Category struct {
	BaseModel
	Name             string      `gorm:"column:name" type:"varchar(20);not null" json:"name"`
	Level            int32       `gorm:"column:level" type:"int;not null;default:1" json:"level"`
	IsTab            bool        `gorm:"column:is_tab" type:"boolean;not null;default:false" json:"is_tab"`
	ParentCategoryID int32       `json:"parent"`
	ParentCategory   *Category   `json:"-"`
	SubCategory      []*Category `gorm:"foreignKey:ParentCategoryID;references:ID" json:"sub_category"`
}

type Brands struct {
	BaseModel
	Name string `gorm:"column:name" type:"varchar(50);not null"`
	Logo string `gorm:"column:logo" type:"varchar(200);not null;default:''"`
}

type GoodsCategoryBrand struct {
	BaseModel
	CategoryID int32 `gorm:"column:category_id" type:"int;index:idx_category_brand,unique"`
	Category   Category

	BrandsID int32 `gorm:"column:brands_id" type:"int;index:idx_category_brand,unique"`
	Brands   Brands
}

type Banner struct {
	BaseModel
	Image string `gorm:"column:image" type:"varchar(200);not null"`
	URL   string `gorm:"column:url" type:"varchar(200);not null"`
	Index int32  `gorm:"column:index" type:"int;not null;default:1"`
}

type Goods struct {
	BaseModel
	CategoryID int32 `gorm:"column:category_id" type:"int;not null"`
	Category   Category

	BrandsID int32 `gorm:"column:brands_id" type:"int;not null"`
	Brands   Brands

	OnSale   bool `gorm:"column:on_sale" type:"boolean;default:false;not null"`   // 是否上架
	ShipFree bool `gorm:"column:ship_free" type:"boolean;default:false;not null"` // 是否免运费
	IsNew    bool `gorm:"column:is_new" type:"boolean;default:false;not null"`    // 是否新品
	IsHot    bool `gorm:"column:is_hot" type:"boolean;default:false;not null"`    // 是否热卖

	Name        string  `gorm:"column:name" type:"varchar(50);not null"`
	GoodsSn     string  `gorm:"column:goods_sn" type:"varchar(50);not null"`
	ClickNum    int32   `gorm:"column:click_num" type:"int;not null;default:0"` // 商品点击量
	SoldNum     int32   `gorm:"column:sold_num" type:"int;not null;default:0"`  // 商品售卖量
	FavNum      int32   `gorm:"column:fav_num" type:"int;not null;default:0"`   // 商品收藏量
	MarketPrice float32 `gorm:"column:market_price" type:"float;not null"`      // 商品市场价格
	ShopPrice   float32 `gorm:"column:shop_price" type:"float;not null"`        // 商品本店价格

	GoodsBrief      string   `gorm:"column:goods_brief" type:"varchar(100);not null"` // 商品简介
	Images          GormList `gorm:"column:images" type:"varchar(2000);not null"`
	DescImages      GormList `gorm:"column:desc_images" type:"varchar(2000);not null"`
	GoodsFrontImage string   `gorm:"column:goods_front_image" type:"varchar(200);not null"` // 商品首页图
}

// 以下为gorm框架钩子方法：当我们数据库完成增加、删、改时时，会进行回调，然后去修改对应ES中的数据逻辑
// 但是我们如何保证数据一致性？？？

func (g *Goods) AfterCreate(tx *gorm.DB) (err error) {
	esModel := EsGoods{
		ID:          g.ID,
		CategoryID:  g.CategoryID,
		BrandsID:    g.BrandsID,
		OnSale:      g.OnSale,
		ShipFree:    g.ShipFree,
		IsNew:       g.IsNew,
		IsHot:       g.IsHot,
		Name:        g.Name,
		ClickNum:    g.ClickNum,
		SoldNum:     g.SoldNum,
		FavNum:      g.FavNum,
		MarketPrice: g.MarketPrice,
		GoodsBrief:  g.GoodsBrief,
		ShopPrice:   g.ShopPrice,
	}

	_, err = global.ES.Index().Index(esModel.GetIndexName()).BodyJson(esModel).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}

func (g *Goods) AfterUpdate(tx *gorm.DB) (err error) {
	esModel := EsGoods{
		ID:          g.ID,
		CategoryID:  g.CategoryID,
		BrandsID:    g.BrandsID,
		OnSale:      g.OnSale,
		ShipFree:    g.ShipFree,
		IsNew:       g.IsNew,
		IsHot:       g.IsHot,
		Name:        g.Name,
		ClickNum:    g.ClickNum,
		SoldNum:     g.SoldNum,
		FavNum:      g.FavNum,
		MarketPrice: g.MarketPrice,
		GoodsBrief:  g.GoodsBrief,
		ShopPrice:   g.ShopPrice,
	}

	_, err = global.ES.Update().Index(esModel.GetIndexName()).
		Doc(esModel).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}

func (g *Goods) AfterDelete(tx *gorm.DB) (err error) {
	_, err = global.ES.Delete().Index(EsGoods{}.GetIndexName()).Id(strconv.Itoa(int(g.ID))).Do(context.Background())
	if err != nil {
		return err
	}
	return nil
}
